package cn.chenfeifx.core.controls;

import cn.chenfeifx.core.common.*;
import javafx.beans.property.*;
import javafx.geometry.Insets;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.*;

public class CFStage extends Stage {

    private static final String ROOT_STYLE_SHEET = ResourcesLoader.load("/cn/chenfeifx/core/css/cf-base.css");
    private final ObjectProperty<Insets> insetsPro = new SimpleObjectProperty<>(new Insets(10));
    private final BooleanProperty maximizePro = new SimpleBooleanProperty(false);
    private final DoubleProperty arcPro = new SimpleDoubleProperty(6); // 窗口圆角程度
    private double arc;
    private double height = 650;
    private double width = 1100;
    private CFBounds cfBounds;
    private StageDragResizer stageDragResizer;

    private final BorderPane content = new BorderPane(); // 内容区域
    private final HBox container = new HBox(new StackPane(), content);
    private final StackPane backdrop = new StackPane(container); // 背景区域，为了展示阴影效果
    private final StackPane root = new StackPane(backdrop); // 根节点
    private final Scene scene = new Scene(root);

    //
    private final CFHeader cfHeader = new CFHeader();

    public CFStage() {
        initialize();
    }

    public CFStage(Node node) {
        setContent(node);
        initialize();
    }

    public CFStage(Node root, double width, double height) {
        setContent(root);
        this.height = height;
        this.width = width;
        initialize();
    }

    final public CFStage setArc(double arcPro) {
        this.arcPro.set(arcPro);
        return this;
    }

    final public void setContent(Node main) {
        this.content.setCenter(main);
    }

    final public CFStage setAside(StackPane aside) {
        this.container.getChildren().set(0, aside);
        return this;
    }

    final public CFStage setHeaderStyle(CFHeader.HeaderStyle headerStyle) {
        if (!CFHeader.HeaderStyle.ALL.equals(headerStyle)) {
            stageDragResizer.setEnable(false);
        }
        if (CFHeader.HeaderStyle.NONE.equals(headerStyle)) {
            content.setTop(null);
        }
        cfHeader.setHeaderStyle(headerStyle);
        return this;
    }

    final public CFStage setHeaderColor(Color color) {
        cfHeader.setBackground(new Background(new BackgroundFill(color, null, null)));
        return this;
    }

    final public CFStage setHeaderTitle(Node node) {
        cfHeader.setTitle(node);
        return this;
    }

    final public CFStage setMinSize(double width, double height) {
        setMinWidth(width);
        setMinHeight(height);
        this.root.setMinSize(width, height);
        return this;
    }

    final public StackPane getBackdrop() {
        return backdrop;
    }

    /**
     * 设置背景图片:默认背景为白色
     *
     * @param image
     */
    final public CFStage setBackdropImage(Image image) {
        BackgroundSize backgroundSize = new BackgroundSize(-1, -1, false, false, false, true);
        BackgroundImage backgroundImage = new BackgroundImage(image, null, null, BackgroundPosition.DEFAULT, backgroundSize);
        Background background = new Background(backgroundImage);
        this.container.setBackground(background);
        return this;
    }

    private void initialize() {
        setTitle("CHENFEI-FXUI");// 标题
        getIcons().add(ResourcesLoader.loadFxImage("/cn/chenfeifx/core/img/logo.png"));// icon
        initStyle(StageStyle.TRANSPARENT); // 修改窗口样式
        scene.setFill(null);
        scene.getStylesheets().add(ROOT_STYLE_SHEET);// 加载基础样式
        setScene(scene);
        root.setBackground(null);
        container.setBackground(new Background(new BackgroundFill(Color.rgb(255, 255, 255, 1), null, null))); // 窗口默认颜色
        HBox.setHgrow(content, Priority.ALWAYS);
        //裁剪为圆角
        FxUtil.clipRect(container, arcPro);
        //显示阴影效果
        backdrop.setEffect(new DropShadow(BlurType.THREE_PASS_BOX, Color.rgb(0, 0, 0, 0.5), 10, 0, 1.5, 1.5));
        this.root.setPrefHeight(height + insetsPro.get().getBottom() * 2);
        this.root.setPrefWidth(width + insetsPro.get().getBottom() * 2);
        this.root.paddingProperty().bind(insetsPro);
        // header
        content.setTop(cfHeader);
        cfHeader.bindTitleText(titleProperty());
        headerEvent();
        //窗口移动和缩放
        stageMove();
        stageDragResizer = new StageDragResizer(this, this.root, 10);// 窗口拖动缩放
    }

    /**
     * 窗口事件监听
     */
    private void headerEvent() {
        cfHeader.setOnMouseClicked(event -> { // 双击header 放大，缩小。
            if (event.getClickCount() == 2) {
                maximizePro.set(!maximizePro.get());
            }
        });
        cfHeader.setMaximizeMouseClicked(event -> maximizePro.set(!maximizePro.get()));
        maximizePro.addListener((observable, oldValue, newValue) -> {
            if (newValue) {
                cfBounds = CFBounds.get(new Rectangle2D(getX(), getY(), getWidth(), getHeight()));
                arc = arcPro.get();
                //获取主屏幕的可视边界
                CFBounds visualBounds = CFBounds.get(Screen.getPrimary().getVisualBounds());
                insetsPro.set(new Insets(0));
                arcPro.set(0);
                setWidth(visualBounds.getWidth());
                setHeight(visualBounds.getHeight());
                setX(visualBounds.getMinX());
                setY(visualBounds.getMinY());
                stageDragResizer.setEnable(false);
            } else {
                insetsPro.set(new Insets(10));
                arcPro.set(arc);
                setWidth(cfBounds.getWidth());
                setHeight(cfBounds.getHeight());
                setX(cfBounds.getMinX());
                setY(cfBounds.getMinY());
                stageDragResizer.setEnable(true);
            }
            cfHeader.setMaximizeTooltipText(newValue ? "向下还原" : "最大化");
        });
        cfHeader.setIconifyMouseClicked(event -> setIconified(true));
        cfHeader.setCloseMouseClicked(event -> // 模拟触发事件：WindowEvent.WINDOW_CLOSE_REQUEST
                fireEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSE_REQUEST)));
        // 截取当前窗口为图片功能
        cfHeader.setOnMouseClicked(event -> {
            event.consume();
            if (MouseButton.SECONDARY.equals(event.getButton())) { // 右击
                ClipboardUtils.setSnapshotImage(container);
            }
        });
    }

    /**************************************************** 窗口拖动 ****************************************************/

    private double xOffset;
    private double yOffset;

    private void stageMove() {
        this.cfHeader.setOnMousePressed(event -> {
            event.consume();
            this.xOffset = this.getX() - event.getScreenX();
            this.yOffset = this.getY() - event.getScreenY();
        });
        this.cfHeader.setOnMouseDragged(event -> {
            event.consume();
            if (!maximizePro.get()) {
                this.setX(event.getScreenX() + this.xOffset);
                this.setY(event.getScreenY() + this.yOffset);
            }
        });
    }
}
